home *** CD-ROM | disk | FTP | other *** search
- /*
- (c) 1995-2000 by Wilhelm Noeker (wnoeker@t-online.de)
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA
-
- */
-
- /*========================================================================*\
- | File: strstuff.c Date: 20 Sep 1997 |
- *------------------------------------------------------------------------*
- | Some string functions, similar to those from the standard library |
- | in <string.h>, but more flexible. |
- | You must call str_setup() before using any of these functions !!! |
- | |
- \*========================================================================*/
-
- #include <stddef.h>
- #include <stdio.h>
- #include "strstuff.h"
-
- UBYTE to_upper[ 256 ]; /* conversion table */
- int is_space[ 256 ]; /* lookup table */
- int bordermode, case_sense;
-
-
-
- /*
- * Set up a to_upper[] table that can convert all national characters from
- * the ISO 8859-1/ECMA 94 charset to uppercase, not only 'a'-'z'.
- * Depending on the global variable <case_sense> this table may just as
- * well do nothing at all.
- * Similarly, the is_space[] table which is built here may call anything
- * but alphanumerics a 'space', depending on the setting of <bordermode>.
- */
- void str_setup( int bm, int cs )
- {
- int c, d;
-
- bordermode = bm;
- case_sense = cs; /* set global variables */
- for( c = 0; c < 256; c++ )
- {
- to_upper[ c ] = c;
- is_space[ c ] = ( bordermode < 2 || (c & 0x7f) <= ' ' );
- }
- for( c = 'a'; c <= 'z'; c++ )
- {
- d = c + 'A' - 'a';
- to_upper[ c ] = d;
- is_space[ c ] = 0;
- is_space[ d ] = 0;
- }
- for( c = '0'; c <= '9'; c++ )
- {
- is_space[ c ] = 0;
- }
- for( c = 224; c < 256; c++ )
- if( c != 247 )
- { /* 247 is the division sign -:- */
- d = c - 32;
- is_space[ c ] = 0;
- is_space[ d ] = 0;
- if( c != 255 ) /* and don't convert '"y' to 'ss' : ) */
- to_upper[ c ] = d;
- }
- if( case_sense ) /* destroy the to_upper[] table again */
- for( c = 0; c < 256; c++ )
- to_upper[ c ] = c;
- is_space[ 0 ] = 0; /* important, will be taken advantage of! */
- }
-
-
-
- /*
- * str_cmp() will work like strcmp() if( case_sense && bordermode == 3 ),
- * but can change its behaviour depending on those variables.
- * Will also indicate by special (but legal) return values if <s> was an
- * abbreviation of <t> or vice versa.
- */
- int str_cmp( UBYTE *s, UBYTE *t )
- {
- if( bordermode < 3 )
- { /* modes where number of 'spaces' doesn't count */
- while( is_space[ *s ] )
- s++; /* advance to first word */
- while( is_space[ *t ] )
- t++;
- while( to_upper[ *s ] == to_upper[ *t ] )
- {
- if( *s == '\0' )
- return 0;
- s++;
- t++;
- if( !bordermode || (is_space[ *s ] && is_space[ *t ]) )
- {
- /* both at the end of a word OR in sloppy bordermode */
- while( is_space[ *s ] )
- s++; /* skip the spaces */
- while( is_space[ *t ] )
- t++;
- }
- }
- }
- else
- {
- while( to_upper[ *s ] == to_upper[ *t ] )
- {
- if( *s == '\0' )
- return 0;
- s++;
- t++;
- }
- }
- if( *s == '\0' )
- return STR_SHORTER;
- else if( *t == '\0' )
- return STR_LONGER;
- else
- return( to_upper[ *s ] - to_upper[ *t ] );
- }
-
-
-
- /*
- * The same as str_cmp(), but will only compare up to <n> characters.
- * (Only two lines of code are different.)
- */
- int strn_cmp( UBYTE *s, UBYTE *t, size_t n )
- {
- if( bordermode < 3 )
- {
- while( is_space[ *s ] )
- s++;
- while( is_space[ *t ] )
- t++;
- while( to_upper[ *s ] == to_upper[ *t ] )
- {
- if( --n == 0 || *s == '\0' )
- return 0; /* that's the difference */
- s++;
- t++;
- if( !bordermode || (is_space[ *s ] && is_space[ *t ]) )
- {
- while( is_space[ *s ] )
- s++;
- while( is_space[ *t ] )
- t++;
- }
- }
- }
- else
- {
- while( to_upper[ *s ] == to_upper[ *t ] )
- {
- if( --n == 0 || *s == '\0' )
- return 0; /* and here once more */
- s++;
- t++;
- }
- }
- if( *s == '\0' )
- return STR_SHORTER;
- else if( *t == '\0' )
- return STR_LONGER;
- else
- return( to_upper[ *s ] - to_upper[ *t ] );
- }
-
-
-
- /*
- * Find a copy of t in s, like strstr( )does.
- * Note that bordermode has NO effect here!
- */
- UBYTE *str_str( UBYTE *s, UBYTE *t )
- {
- int c;
-
- while( *s )
- {
- c = str_cmp( s, t );
- if( c == 0 || c == STR_LONGER )
- return s;
- s++;
- }
- return NULL;
- }
-
-
-
- /*
- * Some user info printed to <stdout>.
- */
- void print_strstat( void )
- {
- printf( "string processing:\n" );
- printf( " upper-/lowercase: " );
- if( case_sense )
- printf( "strict\n" );
- else
- printf( "'ABC'='abc'\n" );
- printf( " word delimiters: " );
- switch( bordermode )
- {
- case 0:
- printf( "'a,b c'='abc'\n" );
- break;
- case 1:
- printf( "'a, b, c'='a,b c'\n" );
- break;
- case 2:
- printf( "'a b c'='a b c'\n" );
- break;
- case 3:
- printf( "strict\n" );
- break;
- }
- }
-
-